package edu.cmu.abi.track;
import edu.cmu.abi.track.Attribute;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.lang.ArrayUtils;


public class Characteristic{
	private ArrayList<Attribute> attributes = new ArrayList<Attribute>();
	private double segmentInterval=-1;
	private int numOfColumns=-1;
	private double[] segmentStartsReal=new double[0];
	private int[] segmentIntervals = new int[0];
	
	public Characteristic (double [] values,int numOfColumns,double segmentSize, double[] segmentStarts){
		this.numOfColumns=numOfColumns;
		this.segmentStartsReal=segmentStarts;
		calculateSegmentIntervals(segmentStarts,segmentSize);
		extractAttributes(values,numOfColumns);
	}
	
	private void calculateSegmentIntervals(double[] segmentStarts, double segmentSize) {
		//get length of track in seconds
		double sum = 0;
		for(int i =0; i<segmentStarts.length;i++)
			sum+=segmentStarts[i];
		
		//calculate interval for each segment in seconds
		double segmentInterval =  sum*segmentSize;
		this.segmentInterval=segmentInterval;
		
		//calculate the start index (inclusive) and end index (exclusive) for each
		//each segment in the given segmentStarts array
		double tempTotal = 0;
		ArrayList<Integer> tempSegmentIntervals = new ArrayList<Integer>();
		for(int i =0; i<segmentStarts.length;i++){
			tempTotal+=segmentStarts[i];
			if(tempTotal>=this.segmentInterval){
				int end = tempTotal>this.segmentInterval?i-1:i;
				tempSegmentIntervals.add(end);
				i--;tempTotal=0;
			}
		}
		segmentIntervals = ArrayUtils.toPrimitive(tempSegmentIntervals.toArray(new Integer[0]));
	}

	public int getNumOfSegment(){
		return segmentIntervals.length;
	}
	
	public ArrayList<Attribute> getAttributes() {
		return attributes;
	}

	public void setAttributes(ArrayList<Attribute> attributes) {
		this.attributes = attributes;
	}

	public double getSegmentInterval() {
		return segmentInterval;
	}

	public void setSegmentInterval(double segmentInterval) {
		this.segmentInterval = segmentInterval;
	}

	public int getNumOfColumns() {
		return numOfColumns;
	}

	public void setNumOfColumns(int numOfColumns) {
		this.numOfColumns = numOfColumns;
	}

	public double[] getSegmentStartsReal() {
		return segmentStartsReal;
	}

	public void setSegmentStartsReal(double[] segmentStartsReal) {
		this.segmentStartsReal = segmentStartsReal;
	}

	public int[] getSegmentIntervals() {
		return segmentIntervals;
	}

	public void setSegmentIntervals(int[] segmentIntervals) {
		this.segmentIntervals = segmentIntervals;
	}

	private void extractAttributes(double [] values,int numOfColumns){
		double[][] columns = unconcatnate(values,numOfColumns);
		
		int count=0;
		for(double[] column:columns){
			attributes.add(new Attribute(count,column,this.segmentIntervals));
			count++;
		}
	}
	private double[][] unconcatnate (double[] array, int numOfColumns){
		double[][] list = new double[numOfColumns][];
		int rows = array.length/numOfColumns;
		ArrayList<Double> tempList;
		for(int column =0; column<12;column++){
			int row = 0;
			tempList= new ArrayList<Double>();
			while(row<rows){
				tempList.add(array[row++*12+column]);
			}
			list[column]=ArrayUtils.toPrimitive(tempList.toArray(new Double[0]));
		}		
		return list;
	}	
	public double[] getSegmentsMean(){
		Iterator<Attribute> it = this.attributes.iterator();
		ArrayList<Double> list = new ArrayList<Double>();
		
		while(it.hasNext()){
			Attribute at = it.next();
			double temp[] = at.getMeans();
			for(double d:temp)
				list.add(d);
		}
		return ArrayUtils.toPrimitive((Double[]) list.toArray(new Double[0]));
	}
	public double[] getSegmentsVariance(){
		Iterator<Attribute> it = this.attributes.iterator();
		ArrayList<Double> list = new ArrayList<Double>();
		
		while(it.hasNext()){
			Attribute at = it.next();
			double temp[] = at.getVariances();
			for(double d:temp)
				list.add(d);
		}
		return ArrayUtils.toPrimitive((Double[]) list.toArray(new Double[0]));
	}
	
	public String toString(){
		StringBuffer sb = new StringBuffer();
		Iterator<Attribute> atts = attributes.iterator();
		while(atts.hasNext()){
			Attribute att = (Attribute)atts.next();
			sb.append(att.toString());
		}
		return sb.toString();
	}
}
